package vn.sms.lazylove.gui;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Stack;

import vn.sms.lazylove.R;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.PhoneLookup;
import android.util.Log;
import android.widget.ImageView;

public class ContactAvatarLoader {

	private static final String LOG_TAG = ContactAvatarLoader.class.getSimpleName();

	private static ContactAvatarLoader shareInstance;

	public static final int user_image_id = R.drawable.ic_avatar_default;

	private Context context;

	// private Bitmap defaultImage;

	public static ContactAvatarLoader getInstance(Context context) {
		if (shareInstance == null) {
			shareInstance = new ContactAvatarLoader(context);
		}
		return shareInstance;
	}

	private ContactAvatarLoader(Context ctx) {
		photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
		context = ctx;

	}

	public void DisplayImage(String phone, Activity activity,
			ImageView imageView, int defaultImageResID) {
		imageView.setTag(phone);

		queuePhoto(phone, activity, imageView);
		imageView.setImageResource(defaultImageResID);

	}

	private void queuePhoto(String phone, Activity activity, ImageView imageView) {
		photosQueue.Clean(imageView);
		PhotoToLoad p = new PhotoToLoad(phone, imageView);
		synchronized (photosQueue.photosToLoad) {
			photosQueue.photosToLoad.push(p);
			photosQueue.photosToLoad.notifyAll();
		}

		if (photoLoaderThread.getState() == Thread.State.NEW)
			photoLoaderThread.start();
	}

	private Bitmap getContactPhoto(String phoneNumber) {
		try {
			Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
		    Uri photoUri = null;
		    ContentResolver cr = context.getContentResolver();
		    Cursor contact = cr.query(phoneUri,
		            new String[] { ContactsContract.Contacts._ID }, null, null, null);

		    if (contact.moveToFirst()) {
		        long userId = contact.getLong(contact.getColumnIndex(ContactsContract.Contacts._ID));
		        photoUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, userId);

		    }
		    if (photoUri != null) {
		        InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(
		                cr, photoUri);
		        if (input != null) {
		            return BitmapFactory.decodeStream(input);
		        }
		    } 
		} catch (Exception e) {
			// TODO: handle exception
			return null;
		}			
		return null;

	}

	private class PhotoToLoad {
		public String phone;
		public ImageView imageView;

		public PhotoToLoad(String u, ImageView i) {
			phone = u;
			imageView = i;
		}
	}

	PhotosQueue photosQueue = new PhotosQueue();

	public void stopThread() {
		photoLoaderThread.interrupt();
	}

	// stores list of photos to download
	class PhotosQueue {
		private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();

		// removes all instances of this ImageView
		public void Clean(ImageView image) {
			for (int j = 0; j < photosToLoad.size();) {
				if (photosToLoad.get(j).imageView == image)
					photosToLoad.remove(j);
				else
					++j;
			}
		}
	}

	class PhotosLoader extends Thread {
		public void run() {
			try {
				while (true) {
					// thread waits until there are any images to load in the
					// queue
					if (photosQueue.photosToLoad.size() == 0)
						synchronized (photosQueue.photosToLoad) {
							photosQueue.photosToLoad.wait();
						}
					if (photosQueue.photosToLoad.size() != 0) {
						PhotoToLoad photoToLoad;
						synchronized (photosQueue.photosToLoad) {
							photoToLoad = photosQueue.photosToLoad.pop();
						}
						Bitmap bmp = getContactPhoto(photoToLoad.phone);
						if (bmp != null) {

							if (((String) photoToLoad.imageView.getTag())
									.equals(photoToLoad.phone)) {
								BitmapDisplayer bd = new BitmapDisplayer(bmp,
										photoToLoad.imageView);
								Activity a = (Activity) photoToLoad.imageView
										.getContext();
								a.runOnUiThread(bd);
				
							}
						}

					}
					if (Thread.interrupted())
						break;
				}
			} catch (InterruptedException e) {
				Log.e(LOG_TAG, "What? ~~~> " + e.getMessage());
			}
		}
	}

	PhotosLoader photoLoaderThread = new PhotosLoader();

	// Used to display bitmap in the UI thread
	class BitmapDisplayer implements Runnable {
		Bitmap bitmap;
		ImageView imageView;

		public BitmapDisplayer(Bitmap b, ImageView i) {
			bitmap = b;
			imageView = i;
		}

		public void run() {
			if (bitmap != null)
				imageView.setImageBitmap(bitmap);
			else {
				imageView.setImageResource(user_image_id);
			}

		}
	}

	public void clearCache() {
		// clear memory cache
	}

	public boolean isAlive() {
		return photoLoaderThread.isAlive();
	}

	public static void copyStream(InputStream is, OutputStream os) {
		final int buffer_size = 1024;
		try {
			byte[] bytes = new byte[buffer_size];
			for (;;) {
				int count = is.read(bytes, 0, buffer_size);
				if (count == -1)
					break;
				os.write(bytes, 0, count);
			}
		} catch (Exception ex) {
		}
	}
}
